/*
 * Copyright (c) 2025 HiEasyX
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * \file hex.h
 * \brief The HiEasyX major code
 */

#pragma once

#include <include/hex_string.h>
#include <include/impl/hex_impl.h>
#include <include/hex_button.h>
#include <include/hex_window.h>
#include <include/hex_text.h>
#include <include/hex_slider.h>
#include <include/hex_canvas.h>
#include <include/hex_text_input.h>
#include <include/impl/EasyX/hex_easyx.h>
#include <include/hex_image.h>
#include <include/hex_dropdown.h>
#include <include/hex_checkbox.h>
#include <include/hex_checkbox_group.h>
#include <include/hex_scroller.h>

struct HXTheme;
struct HXWindow;
struct HXScroller;
struct HXLayoutContext;
struct HXRuntimeContext;

namespace HX {
/**
 * Get the runtime context of HiEasyX
 * @return The runtime context of HiEasyX
 */
HXRuntimeContext &GetContext();

/**
 * Get the theme of the HiEasyX
 * @return The theme of the HiEasyX
 */
HXTheme &GetTheme();

/**
 * Create the theme for HiEasyX
 */
void CreateTheme();

/**
 * Setting the API of the current OS
 * @param API The API of the OS
 */
void OSAPI(HXOSOperation *API);

/**
 * Setting the buffer where the rendering result will be displayed
 * @param Buffer The buffer to be rendered
 */
void SetBuffer(void *Buffer);

/**
 * Getting the last error in string format
 * @return The last error in string format
 */
HXString GetLastError();

/**
 * Init the HiEasyX UI, preparing for UI layout
 * @param RenderContext The context for rendering
 */
void Begin(HXContext *RenderContext);

/**
 * Setting the message sender
 * @param Sender The sender to be set
 */
void MessageSender(HXMessageSender *Sender);

/**
 * Pushing the message to the message query
 * @param Message The message to be pushed
 * @param Size The size of the message structure
 */
void PushMessage(void *Message);

/**
 * End the UI layout progress
 */
void End();

/**
 * Check whether the operation has any error
 * @return If there is an error, returning true, nor returning false
 */
bool Wined();

/**
 * Render the UI to the buffer
 */
void Render();

/**
 * Set the gap between controls
 * @param Gap The gap between control
 */
void SetControlGap(HXGInt Gap);

/**
 * Setting a new baseline for control layout
 * @param BaseLine The new baseline to be setted
 */
void SetBaseLine(HXGInt BaseLine);

/**
 * Clipping the coord into the relative coord
 * @param Point The point needed to clip
 * @return The clipped coord
 */
HXPoint ClipCoord(HXPoint Point);

/**
 * Counting the new layout position for next control
 * @param Size The size of the new inserted control
 */
void LayoutNextControl(HXPoint Size);

/**
 * Get the current layout position
 * @return The position of the current layout
 */
HXPoint CurrentLayoutPosition();

/**
 * Getting the current working painter
 * @return The current working painter
 */
HXBufferPainter *CurrentPainter();

/**
 * Get the visibility of current context
 * @param Size The size of the control
 * @return If the return value is true, the controls are all visible, nor invisible
 */
bool CurrentVisibility(HXPoint Size);

/**
 * Check whether the window is folded
 * @return If the window is folded, returning true, nor false
 */
bool RoughVisibility();

/**
 * Check the visibility more accurately
 * @param Size The size of the control
 * @return If the control is invisible, returning false
 */
bool AccVisibility(HXPoint Size);

/**
 * Get whether the control needs to calculate the layout
 * @return If the control needs, returning true, nor false
 */
bool NeedLayoutCal();

/**
 * Set the next control and its follow will keep the same line of the current control
 */
void BeginSameLine();

/**
 * Getting the current layout
 * @return The pointer to the current layout
 */
HXLayoutContext *CurrentLayout();

/**
 * Setting the left margin of this layout
 * @param Margin The size of the left margin
 */
void SetLeftMargin(HXGInt Margin);

/**
 * Returning to normal layout
 */
void EndSameLine();
}

/**
 * The type of controls
 */
enum class HXControlType {
	Button
};

/**
 * The status of a control
 */
enum class HXControlStatus {
	Button_Hovering
};

/**
 * The structure to store controls
 */
struct HXControl {
	HXControlType   Type;
	HXString        Id;
	HXControlStatus Status;
};

struct HXLayoutContext {
	HXGInt BaseLine         = 50;
	bool   InSameLine       = false;
	bool   LockingSameLine  = false;
	HXGInt LeftPadding      = 0;
	HXGInt LeftPaddingValue = 0;
	HXGInt LeftMargin       = 5;
	HXRect AvailableRegion{};
	HXGInt CurrentHeightMax = 0;
	HXGInt ControlGap       = 5;
};

struct HXScroller {
	HXBufferPainter *Painter;
	HXLayoutContext  Layout;
	bool             Visible = true;
	HXScroller *     Last;
};

/**
 * The structure to store the window, including title, position and controls
 */
struct HXWindow {
	HXString         Title;
	HXPoint          Size;
	HXPoint          Where;
	HXBufferPainter *Painter;
	bool             Folded;
	HXLayoutContext  Layout;
	HXLayoutContext *CurrentLayout;

	HXGInt      ScrollerX = 0;
	HXGInt      ScrollerY = 0;
	HXScroller *Scroller  = nullptr;

	~HXWindow() {
		delete Painter;
	}
};

/**
 * The theme structure for HiEasyX
 */
struct HXTheme {
	HXColor SplitLine;
	HXColor WindowBackground;
	HXColor WindowTitleText;
	HXColor WindowTitleBackground;
	HXColor ButtonBorder;
	HXColor ButtonBackground;
	HXColor ButtonText;
	HXColor ButtonOnHoverBorder;
	HXColor ButtonOnHoverBackground;
	HXColor ButtonOnHoverText;
	HXColor ButtonPressedBorder;
	HXColor ButtonPressedBackground;
	HXColor ButtonPressedText;
	HXColor SliderText;
	HXColor SliderBackground;
	HXColor SliderActiveText;
	HXColor SliderActiveBackground;
	HXColor SliderBox;
	HXColor CheckboxBackground;
	HXColor CheckboxActiveCross;
	HXColor CheckboxText;
	HXColor ScrollerBackground;
	HXColor DropdownBackground;
	HXColor DropdownBorder;
	HXColor DropdownText;
	HXColor DropdownHoverBackground;
	HXColor DropdownHoverBorder;
	HXColor DropdownHoverText;
	HXColor TextInputBackground;
	HXColor TextInputBorder;
	HXColor TextInputText;
	HXColor TextInputSelectedBackground;
	HXColor TextInputCursorColor;
};

/**
 * The runtime context, including all value for UI running
 */
struct HXRuntimeContext {
	std::vector<HXMessage>  MessageQuery;
	std::vector<HXWindow *> Windows;
	HXWindow *              CurrentWindow = nullptr;
	HXContext *             RenderContext = nullptr;
	HXOSOperation *         OSAPI         = nullptr;
	void *                  LocalBuffer   = nullptr;
	HXString                LastError;
	bool                    Initialized = false;
	bool                    Win         = true;
};
